package com.alibaba.yinan.domain.resource.domain;

import com.alibaba.yinan.domain.resource.CassetteType;
import com.alibaba.yinan.domain.resource.ResourceStatus;
import com.alibaba.yinan.domain.resource.ResourceType;
import com.alibaba.yinan.domain.task.Task;
import lombok.Data;
import lombok.Getter;

import java.util.*;

/**
 * @ClassName Cassette
 * @Author mengke
 * @create 2025/8/17 16:12
 * @Description 载具
 */
@Data
public class Cassette extends BaseResource {

    /**
     * 载具槽位
     */
    private final Map<String, ContainerSlot> slots;

    /**
     * 载具类型
     */
    private final CassetteType cassetteType;

    /**
     * 载具存储槽位
     */
    private final BaseStorageSlot storageSlot;

    /**
     * 载具编号
     */
    private String code;


    public Cassette(String code, List<String> slotCodes, CassetteType cassetteType, BaseStorageSlot storageSlot) {
        this.cassetteType = cassetteType;
        this.storageSlot = storageSlot;
        this.code = code;
        this.type = ResourceType.CASSETTE;
        this.status = ResourceStatus.AVAILABLE;
        this.slots = new HashMap<>();
        for (String slotCode : slotCodes) {
            slots.put(slotCode, new ContainerSlot(slotCode));
        }
    }


    public List<ContainerSlot> getFreeSlots() {
        List<ContainerSlot> free = new ArrayList<>();
        for (ContainerSlot slot : slots.values()) {
            if (slot.isFree()) {
                free.add(slot);
            }
        }
        return free;
    }

    public List<ContainerSlot> allocateSlots(String taskId, int num) {
        List<ContainerSlot> allocated = new ArrayList<>();
        for (ContainerSlot slot : slots.values()) {
            if (slot.isFree() && allocated.size() < num) {
                slot.allocate(taskId);
                allocated.add(slot);
            }
        }
        if (allocated.size() < num) {
            allocated.forEach(ContainerSlot::release);
            throw new IllegalStateException("Not enough free slots in cassette " + code);
        }
        return allocated;
    }

    public void releaseSlots(List<ContainerSlot> allocatedSlots) {
        allocatedSlots.forEach(ContainerSlot::release);
    }

    public ContainerSlot getSlotByCode(String code) {
        return slots.get(code);
    }
}
